﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using ComponentFactory.Krypton.Toolkit;

using SceneEngine;

using TreeNode = System.Windows.Forms.TreeNode;

namespace SceneEditor
{
    public partial class Editor
    {
        private LoadingForm loadingForm;

        private string baseImportPath = "Models";

        /// <summary>
        /// Prompts the user to select models to import
        /// into the content project.
        /// </summary>
        private void btnAddAsset_Click(object sender, EventArgs e)
        {
            if (editor.tvAssets.SelectedNode != null &&
                (editor.tvAssets.SelectedNode.Tag == null ||
                (editor.tvAssets.SelectedNode.Parent != null)))
            {
                TreeNode node = editor.tvAssets.SelectedNode;

                if (node.Tag != null)
                {
                    node = node.Parent;
                }

                baseImportPath = node.Text;

                while (node.Parent != null)
                {
                    baseImportPath = Path.Combine(node.Parent.Text, baseImportPath);
                    node = node.Parent;
                }
            }
            else
            {
                baseImportPath = "Models";
            }

            editor.AddAssetForm.BaseImportPath = baseImportPath;

            if (editor.AddAssetForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                //editor.Cursor = System.Windows.Forms.Cursors.WaitCursor;
                editor.tvAssets.Enabled = false;

                editor.btnAddAsset.Enabled = ButtonEnabled.False;
                editor.btnRemoveAsset.Enabled = ButtonEnabled.False;

                loadingForm = new LoadingForm();
                loadingForm.Show();

                loadingForm.backgroundWorker.DoWork += backgroundWorker_DoWork;
                loadingForm.backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;

                List<string>[] arguments = new List<string>[]
                {
                    editor.AddAssetForm.FilePaths,
                    editor.AddAssetForm.FullFilePaths
                };

                loadingForm.backgroundWorker.RunWorkerAsync(arguments);
            }
        }

        void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            PopulateTreeView(editor.tvAssets, e.Result as List<string>, Path.DirectorySeparatorChar);
            
            loadingForm.Close();
            loadingForm.Dispose();

            editor.tvAssets.Enabled = true;

            editor.btnAddAsset.Enabled = ButtonEnabled.Container;
            editor.btnRemoveAsset.Enabled = ButtonEnabled.Container;
        }

        void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            List<string>[] arguments = e.Argument as List<string>[];

            List<string> filePaths = new List<string>();

            string modelsDirectory = Path.Combine(EditorGlobals.ContentPath, baseImportPath);

            for (int i = 0; i < arguments[0].Count; i++)
            {
                string modelPath = arguments[1][i];
                string relativeModelPath = arguments[0][i];

                string modelName = Path.GetFileNameWithoutExtension(modelPath);

                if (Directory.Exists(modelsDirectory) == false)
                {
                    Directory.CreateDirectory(modelsDirectory);
                }

                string destinationPath = Path.Combine(modelsDirectory, relativeModelPath + Path.GetExtension(modelPath));

                if (!File.Exists(destinationPath))
                {
                    if (Directory.Exists(Path.GetDirectoryName(destinationPath)) == false)
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
                    }

                    File.Copy(modelPath, destinationPath);
                }
                else
                {
                    System.Windows.Forms.MessageBox.Show(modelName + "already exists in the Model folder");
                    continue;
                }

                string assetPath = Path.Combine(baseImportPath, relativeModelPath);
                filePaths.Add(assetPath);

                contentBuilder.Add(modelPath, assetPath, null, "EngineModelProcessor");

                loadingForm.backgroundWorker.ReportProgress((int)((float)i / (float)arguments[0].Count * 100.0f) + 1);
            }

            string buildError = contentBuilder.Build(baseImportPath);

            if (!string.IsNullOrEmpty(buildError))
            {
                foreach (string assetPath in filePaths)
                {
                    string filePath = Path.Combine(EditorGlobals.ContentPath, assetPath);

                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }
                }

                System.Windows.Forms.MessageBox.Show(buildError, "Error");
                editor.Cursor = System.Windows.Forms.Cursors.Arrow;

                editor.tvAssets.Enabled = true;

                editor.btnAddAsset.Enabled = ButtonEnabled.Container;
                editor.btnRemoveAsset.Enabled = ButtonEnabled.Container;

                return;
            }

            modelManager.LoadModelsFromDirectory(contentBuilder.OutputDirectory, loadingForm.backgroundWorker);

            e.Result = filePaths;
        }
        /// <summary>
        /// Deletes the currently selected model.
        /// </summary>
        private void btnRemoveAsset_Click(object sender, EventArgs e)
        {
            if (editor.tvAssets.SelectedNode == null)
            {
                return;
            }

            if (editor.tvAssets.SelectedNodes.Count == 1)
            {
                TreeNode selectedItem = editor.tvAssets.SelectedNode;
                RemoveAsset(selectedItem);
            }
            else
            {
                for (int i = editor.tvAssets.SelectedNodes.Count - 1; i >= 0; i--)
                {
                    RemoveAsset(editor.tvAssets.SelectedNodes[i]);
                }
            }
        }

        private void RemoveAsset(TreeNode selectedItem)
        {
            if (selectedItem.Tag == null)
            {
                while (selectedItem.Nodes.Count > 0)
                {
                    TreeNode childNode = selectedItem.Nodes[0];

                    if (childNode != null)
                    {
                        RemoveAsset(childNode);
                    }
                    else
                    {
                        selectedItem.Nodes.RemoveAt(0);
                    }
                }

                string directory = Path.Combine(EditorGlobals.ContentPath, selectedItem.FullPath);
                EditorGlobals.RemoveFolderItem(selectedItem.FullPath);

                if (Directory.GetFiles(directory).Length <= 0)
                {
                    Directory.Delete(directory);
                }

                selectedItem.Remove();
            }

            else
            {
                string filePath = Path.Combine(EditorGlobals.ContentPath, selectedItem.Tag as string);

                string relativeFilePath = Path.GetDirectoryName(selectedItem.Tag as string);

                string modelName = Path.GetFileNameWithoutExtension(filePath);
                string relativeName = Path.Combine(relativeFilePath, modelName);

                string extension = "";

                if (File.Exists(filePath + ".x"))
                {
                    extension = ".x";
                }
                else if (File.Exists(filePath + ".fbx"))
                {
                    extension = ".fbx";
                }
                else
                {
                    return;
                }

                EditorGlobals.RemoveContentItem(relativeName, extension);
                File.Delete(filePath + extension);

                List<string> usedTextures = new List<string>();

                foreach (string model in modelManager.Models.Keys)
                {
                    if (relativeName == model)
                        continue;

                    ModelInformation modelInfo = (ModelInformation)modelManager.Models[model].Tag;

                    string directory = Path.GetDirectoryName(model);

                    foreach (string texturePath in modelInfo.RelativeTexturePaths)
                    {
                        string relativePath = Path.GetFullPath(Path.Combine(EditorGlobals.ContentPath,
                                                               directory,
                                                               texturePath));

                        if (usedTextures.Contains(relativePath) == false)
                        {
                            usedTextures.Add(relativePath);
                        }
                    }
                }

                ModelInformation deletedModelInfo = (ModelInformation)
                    modelManager.Models[relativeName].Tag;

                foreach (string texturePath in deletedModelInfo.RelativeTexturePaths)
                {
                    string directory = Path.GetDirectoryName(relativeName);

                    string relativePath = Path.GetFullPath(Path.Combine(EditorGlobals.ContentPath,
                                                           directory,
                                                           texturePath));

                    if (usedTextures.Contains(relativePath) == false)
                    {
                        File.Delete(relativePath);
                    }
                }

                modelManager.RemoveModel(relativeName);

                selectedItem.Remove();
            }
        }

        private void tvAssets_NodeMouseClick(object sender, System.Windows.Forms.TreeViewEventArgs e)
        {
            TreeNode selectedItem = editor.tvAssets.SelectedNode;

            if (selectedItem == null || editor.tvAssets.SelectedNodes.Count == 0)
            {
                editor.previewControl.ModelName = string.Empty;
                return;
            }

            editor.previewControl.ModelName = selectedItem.Tag as string;
        }

        private void tvAssets_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (editor.tvAssets.SelectedNode == null)
            {
                editor.previewControl.ModelName = string.Empty;
            }
        }
    }
}
